package com.chat.gateway.filter;

import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.chat.common.common.exception.BaseException;
import com.chat.common.dto.AuthRequestDTO;
import com.chat.common.vo.R;
import com.chat.gateway.config.AuthProperties;
import com.chat.openfeign.client.AuthService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 *          这是教学代码
 *          这是教学代码
 *          这是教学代码
 *          这是教学代码
 *
 * @author wei kunJie
 * @date 2024/2/7 15:48:38
 */
@Component
@RequiredArgsConstructor
public class MyLogGateWayFilter implements GlobalFilter, Ordered {

    @Lazy
    @Autowired
    private AuthService authService;

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    private final AuthProperties authProperties;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("Time:" + new Date() + "\t 执行了自定义的全局过滤器: " + "MyLogGateWayFilter" + "hello");

        String path = exchange.getRequest().getURI().getPath();
        System.out.println("Path："+path);
        String host = exchange.getRequest().getURI().getHost();
        int port = exchange.getRequest().getURI().getPort();
        System.out.println("host:port："+host+":"+port);

        ServerHttpRequest request = exchange.getRequest();
        if(isExclude(request.getPath().toString())){
            return chain.filter(exchange);
        }
        AuthRequestDTO authRequestDTO = new AuthRequestDTO();
        authRequestDTO.setUrl(request.getURI().toString());
        List<String> authorization = request.getHeaders().get("token");
        if(authorization != null && !authorization.isEmpty()){
            authRequestDTO.setToken(authorization.get(0));
        }

        CompletableFuture<R> future = CompletableFuture.supplyAsync(() -> {
            try {
                return authService.validateToken(authRequestDTO);
            } catch (BaseException e) {
                // 打印异常信息
                e.printStackTrace();
                // 返回一个默认的结果
                return new R(e.getStatusCode().value(), e.getMessage());
            }
        });

        // 将CompletableFuture转换为Mono
        Mono<R> mono = Mono.fromFuture(future);
        // 使用Mono的结果
        return mono.flatMap(result -> {
            // 根据结果进行处理
            if (result.getCode() == 200) {
                return chain.filter(exchange);  // 验证通过，继续处理请求
            } else {
                ServerHttpResponse response = exchange.getResponse();
//                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                // 将 R 对象转换为 JSON
                JSONConfig config = JSONConfig.create().setIgnoreNullValue(false);
                String json = JSONUtil.toJsonStr(result, config);
                DataBuffer buffer = response.bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8));
                return response.writeWith(Mono.just(buffer));  // 将 JSON 写入响应的 body
            }
        });
//        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;//加载filter的优先级，越小越高
    }

    private boolean isExclude(String path) {
        for (String excludePath : authProperties.getExcludePaths()) {
            if(antPathMatcher.match(excludePath,path)){
                return true;
            }
        }
        return false;
    }
}

